package org.zoomdev.zoom.common.utils;

import java.sql.Timestamp;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 日期时间工具类
 *
 * <p>提供常用的日期时间格式化和解析功能</p>
 */
public final class DateTimeUtils {

    // ==================== 时间单位常量 ====================
    public static final int SECONDS_PER_DAY = 86400; // 3600 * 24
    public static final int MILLIS_PER_DAY = SECONDS_PER_DAY * 1000;
    // 标准日期格式
    public static final String DATE_PATTERN = "yyyy-MM-dd";

    // ==================== 日期时间格式模式 ====================
    public static final String COMPACT_DATE_PATTERN = "yyyyMMdd";
    // 标准时间格式
    public static final String TIME_PATTERN = "HH:mm:ss";
    public static final String COMPACT_TIME_PATTERN = "HHmmss";
    public static final String TIME_WITH_MILLIS_PATTERN = "HH:mm:ss.SSS";
    // 标准日期时间格式
    public static final String DATE_TIME_PATTERN = "yyyy-MM-dd HH:mm:ss";
    public static final String COMPACT_DATE_TIME_PATTERN = "yyyyMMddHHmmss";
    public static final String DATE_TIME_WITH_MILLIS_PATTERN = "yyyy-MM-dd HH:mm:ss.SSS";
    public static final String COMPACT_DATE_TIME_WITH_MILLIS_PATTERN = "yyyyMMddHHmmssSSS";
    // ==================== 预定义格式化器 ====================
    public static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern(DATE_PATTERN);
    public static final DateTimeFormatter COMPACT_DATE_FORMATTER = DateTimeFormatter.ofPattern(COMPACT_DATE_PATTERN);
    public static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern(TIME_PATTERN);
    public static final DateTimeFormatter COMPACT_TIME_FORMATTER = DateTimeFormatter.ofPattern(COMPACT_TIME_PATTERN);
    public static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern(DATE_TIME_PATTERN);
    public static final DateTimeFormatter COMPACT_DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern(COMPACT_DATE_TIME_PATTERN);
    public static final DateTimeFormatter DATE_TIME_WITH_MILLIS_FORMATTER = DateTimeFormatter.ofPattern(DATE_TIME_WITH_MILLIS_PATTERN);
    // ==================== 格式化器缓存 ====================
    private static final ConcurrentHashMap<String, DateTimeFormatter> FORMATTER_CACHE = new ConcurrentHashMap<>();

    /**
     * 预加载常用格式化器到缓存
     */
    static {
        // 确保预定义的格式化器被加载
        FORMATTER_CACHE.put(DATE_PATTERN, DATE_FORMATTER);
        FORMATTER_CACHE.put(COMPACT_DATE_PATTERN, COMPACT_DATE_FORMATTER);
        FORMATTER_CACHE.put(TIME_PATTERN, TIME_FORMATTER);
        FORMATTER_CACHE.put(COMPACT_TIME_PATTERN, COMPACT_TIME_FORMATTER);
        FORMATTER_CACHE.put(DATE_TIME_PATTERN, DATE_TIME_FORMATTER);
        FORMATTER_CACHE.put(COMPACT_DATE_TIME_PATTERN, COMPACT_DATE_TIME_FORMATTER);
        FORMATTER_CACHE.put(DATE_TIME_WITH_MILLIS_PATTERN, DATE_TIME_WITH_MILLIS_FORMATTER);
    }

    private DateTimeUtils() {

    }

    /**
     * 获取或创建DateTimeFormatter（带缓存）
     *
     * @param pattern 日期时间格式模式
     * @return 缓存的DateTimeFormatter实例
     */
    public static DateTimeFormatter ofPattern(String pattern) {
        return FORMATTER_CACHE.computeIfAbsent(pattern, DateTimeFormatter::ofPattern);
    }
    // ==================== 格式化方法 ====================

    /**
     * 使用指定格式化器格式化日期时间
     *
     * @param formatter 日期时间格式化器
     * @param dateTime  要格式化的日期时间
     * @return 格式化后的字符串
     */
    public static String format(DateTimeFormatter formatter, LocalDateTime dateTime) {
        if (formatter == null || dateTime == null) {
            throw new IllegalArgumentException("Formatter and dateTime cannot be null");
        }
        return formatter.format(dateTime);
    }

    /**
     * 将日期时间格式化为标准格式字符串 (yyyy-MM-dd HH:mm:ss)
     *
     * @param dateTime 要格式化的日期时间
     * @return 格式化后的字符串
     */
    public static String formatToStandardDateTime(LocalDateTime dateTime) {
        return format(DATE_TIME_FORMATTER, dateTime);
    }

    /**
     * 时间戳转字符串
     * @param dateTime
     * @return
     */
    public static String formatToStandardDateTime(Timestamp dateTime) {
        return format(DATE_TIME_FORMATTER, dateTime.toLocalDateTime());
    }

    /**
     * 将日期格式化为标准格式字符串 (yyyy-MM-dd)
     *
     * @param date 要格式化的日期
     * @return 格式化后的字符串
     */
    public static String formatToStandardDate(LocalDate date) {
        if (date == null) {
            throw new IllegalArgumentException("Date cannot be null");
        }
        return DATE_FORMATTER.format(date);
    }

    // ==================== 解析方法 ====================

    /**
     * 使用指定格式化器解析字符串为日期时间
     *
     * @param dateTimeStr 要解析的日期时间字符串
     * @param formatter   日期时间格式化器
     * @return 解析后的日期时间
     * @throws IllegalArgumentException 如果解析失败
     */
    public static LocalDateTime parseToDateTime(String dateTimeStr, DateTimeFormatter formatter) {
        if (dateTimeStr == null || formatter == null) {
            throw new IllegalArgumentException("DateTime string and formatter cannot be null");
        }
        return LocalDateTime.parse(dateTimeStr, formatter);
    }

    /**
     * 解析标准格式日期时间字符串 (yyyy-MM-dd HH:mm:ss)
     *
     * @param dateTimeStr 要解析的日期时间字符串
     * @return 解析后的日期时间
     * @throws IllegalArgumentException 如果解析失败
     */
    public static LocalDateTime parseStandardDateTime(String dateTimeStr) {
        return parseToDateTime(dateTimeStr, DATE_TIME_FORMATTER);
    }

    /**
     * 使用指定格式化器解析字符串为日期
     *
     * @param dateStr   要解析的日期字符串
     * @param formatter 日期格式化器
     * @return 解析后的日期
     * @throws IllegalArgumentException 如果解析失败
     */
    public static LocalDate parseToDate(String dateStr, DateTimeFormatter formatter) {
        if (dateStr == null || formatter == null) {
            throw new IllegalArgumentException("Date string and formatter cannot be null");
        }
        return LocalDate.parse(dateStr, formatter);
    }

    /**
     * 解析标准格式日期字符串 (yyyy-MM-dd)
     *
     * @param dateStr 要解析的日期字符串
     * @return 解析后的日期
     * @throws IllegalArgumentException 如果解析失败
     */
    public static LocalDate parseStandardDate(String dateStr) {
        return parseToDate(dateStr, DATE_FORMATTER);
    }

    // ==================== 实用方法 ====================

    /**
     * 获取当前日期时间的标准格式字符串
     *
     * @return 当前日期时间的标准格式字符串 (yyyy-MM-dd HH:mm:ss)
     */
    public static String nowAsString() {
        return formatToStandardDateTime(LocalDateTime.now());
    }

    /**
     * 获取当前日期的标准格式字符串
     *
     * @return 当前日期的标准格式字符串 (yyyy-MM-dd)
     */
    public static String todayAsString() {
        return formatToStandardDate(LocalDate.now());
    }


    /**
     * 将Timestamp转换为LocalDateTime
     *
     * @param timestamp 时间戳对象
     * @return LocalDateTime对象
     */
    public static LocalDateTime toLocalDateTime(Timestamp timestamp) {
        if (timestamp == null) {
            return null;
        }
        return timestamp.toLocalDateTime();
    }

    /**
     * 将LocalDateTime转换为Timestamp
     *
     * @param dateTime 本地日期时间对象
     * @return Timestamp对象
     */
    public static Timestamp toTimestamp(LocalDateTime dateTime) {
        if (dateTime == null) {
            return null;
        }
        return Timestamp.valueOf(dateTime);
    }

    public static Timestamp nowTimestamp(){
        return new Timestamp(System.currentTimeMillis());
    }

    /**
     * 将毫秒时间戳转换为LocalDateTime
     *
     * @param epochMilli 从1970-01-01T00:00:00Z开始的毫秒数
     * @return LocalDateTime对象
     */
    public static LocalDateTime toLocalDateTime(long epochMilli) {
        return LocalDateTime.ofInstant(Instant.ofEpochMilli(epochMilli), ZoneId.systemDefault());
    }

    /**
     * 将LocalDate转换为Timestamp（时间部分设为00:00:00）
     *
     * @param date 本地日期对象
     * @return Timestamp对象
     */
    public static Timestamp toTimestamp(LocalDate date) {
        if (date == null) {
            return null;
        }
        return Timestamp.valueOf(date.atStartOfDay());
    }

    /**
     * 将Timestamp转换为LocalDate
     *
     * @param timestamp 时间戳对象
     * @return LocalDate对象
     */
    public static LocalDate toLocalDate(Timestamp timestamp) {
        if (timestamp == null) {
            return null;
        }
        return timestamp.toLocalDateTime().toLocalDate();
    }

    /**
     * 获取当前时间戳
     *
     * @return 当前时间的Timestamp对象
     */
    public static Timestamp currentTimestamp() {
        return new Timestamp(System.currentTimeMillis());
    }

    /**
     * 将LocalDateTime转换为毫秒时间戳（使用系统默认时区）
     *
     * @param dateTime 本地日期时间对象
     * @return 从1970-01-01T00:00:00Z开始的毫秒数
     */
    public static long toEpochMilli(LocalDateTime dateTime) {
        if (dateTime == null) {
            throw new IllegalArgumentException("dateTime不能为null");
        }
        return dateTime.atZone(ZoneId.systemDefault())
                .toInstant()
                .toEpochMilli();
    }


    /**
     * LocalDateTime转秒时间戳（系统默认时区）
     */
    public static long toEpochSecond(LocalDateTime dateTime) {
        if (dateTime == null) {
            throw new IllegalArgumentException("LocalDateTime不能为null");
        }
        return dateTime.atZone(ZoneId.systemDefault())
                .toInstant()
                .getEpochSecond();
    }


    /**
     * 将Date转换为LocalDateTime（使用系统默认时区）
     *
     * @param date 要转换的Date对象
     * @return LocalDateTime对象，如果输入为null则返回null
     */
    public static LocalDateTime toLocalDateTime(Date date) {
        if (date == null) {
            return null;
        }
        return date.toInstant()
                .atZone(ZoneId.systemDefault())
                .toLocalDateTime();
    }

    /**
     * 将LocalDateTime转换为Date（使用系统默认时区）
     *
     * @param dateTime 要转换的LocalDateTime对象
     * @return Date对象，如果输入为null则返回null
     */
    public static Date toDate(LocalDateTime dateTime) {
        if (dateTime == null) {
            return null;
        }
        return Date.from(dateTime.atZone(ZoneId.systemDefault()).toInstant());
    }


}